#include <stdio.h>
#include <ctime>
#include <cstdarg>
#include <calcif.h>

int g_state = 0;

void log_print(int level, char const* const format, ...)
{ 
	char buf[4096] = { 0 };
	int len = 4096;
	auto now = std::chrono::system_clock::now();
	auto now_tt = std::chrono::system_clock::to_time_t(now);
	auto n = std::strftime(buf, len, "%Y-%m-%d %H:%M:%S", std::localtime(&now_tt));
	if (n < len) {
		int millis = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() % 1000;
		n += snprintf(buf + n, len - n, " %d ", millis);
		if (n < len) {
			va_list arg_list;
			va_start(arg_list, format);
			n += vsnprintf(buf + n, len - n, format, arg_list);
			va_end(arg_list);
		}
	}
	printf("%s\n", buf);
}

int main(int argc, char* argv[])
{
	//初始化
	ZQDBLogSet(&log_print);
	ZQDB_CALC_INF zqdb_inf = { 1, argv[argc - 1]
		, [](HNMSG hmsg, size_t* flags)->int
	{
		//回调函数不要做复杂耗时逻辑...
		return 0;
	}
		, [](HZQDB h, ZQDB_NOTIFY_TYPE notify)
	{
		//回调函数不要做复杂耗时逻辑...
		switch (notify)
		{
		case ZQDB_NOTIFY_STATUS: {
			if (!ZQDBIsDisable(h)) {
				switch (h->type)
				{
				case ZQDB_HANDLE_TYPE_EXCHANGE: {
				} break;
				case ZQDB_HANDLE_TYPE_MODULE: {
					g_state = 1;
				} break;
				default: {
					//
				} break;
				}
			}
			else {
				switch (h->type)
				{
				case ZQDB_HANDLE_TYPE_EXCHANGE: {
				} break;
				case ZQDB_HANDLE_TYPE_MODULE: {
					g_state = 0;
				} break;
				default: {
					//
				} break;
				}
			}
		} break;
		case ZQDB_NOTIFY_ADD: {
			
		} break;
		case ZQDB_NOTIFY_REMOVE: {

		} break;
		case ZQDB_NOTIFY_UPDATE: {

		} break;
		default:
			break;
		}
	}
		//TRADE
		, [](HZQDB user, HZQDB code, char direction, char offset, char type, double volume, double price, HNMSG* rsp, size_t timeout) -> int
	{
		return 0;
	}
		, [](HZQDB user, HZQDB order, HNMSG* rsp, size_t timeout) -> int
	{
		return 0;
	}
		, [](HZQDB user, HZQDB position, char type, double volume, double price, HNMSG* rsp, size_t timeout) -> int
	{
		return 0;
	}
	};
	auto rlt = ZQCalcInit(&zqdb_inf);
	if (ZQDB_STATUS_OK != rlt) {
		LOG4E("ZQCalcInit err=%d", rlt);
		return -1;
	}
	//启动
	rlt = ZQCalcStart();
	if (ZQDB_STATUS_OK != rlt) {
		LOG4E("ZQDBStart err=%d", rlt);
		return -2;
	}
	//阻塞等待运行
	ZQDBRun(1, [] {
		switch (g_state)
		{
		case 0: {
			LOG4I("myccd initing...");
			std::this_thread::sleep_for(std::chrono::seconds(3));
		} break;
		case 1: {
			LOG4I("myccd init sucess.");
		}
		default: {
			ZQDBCalcTimer();
			if (g_state % 10 == 0) {
				zqdb::Code code("600000", EXCHANGE_SSE);
				zqdb::Calc::Data data(code, CYC_1MIN, 0
					, CALC_DATA_FLAG_ASYNC_DATA);
				zqdb::Calc::Indicator indicator("MA", data
					, zqdb::Calc::InputAttr(R"({"N":5})", 0));
				int count = indicator.GetDataCount();
				int maxcount = indicator.GetDataMaxCount();
				int line_count = indicator.GetResultValueCount();
				LOG4I("%s.%s count=%d maxcount=%d line_count=%d", code->Code, code->Exchange
					, count, maxcount, line_count);
				if (count > 0 && line_count > 0) {
					auto close = (double*)indicator.GetData(mdb::Field(MDB_FIELD_INDEX(ZQDB, KDATA, CLOSE)));
					auto line = (double*)indicator.GetResultValue(0);
					LOG4I("%s.%s first close=%.2f, last close=%.2f first line=%.2f, last line=%.2f", code->Code, code->Exchange
						, close[0], close[count - 1], line[0], line[count - 1]);
				}
			}
			g_state++;
			std::this_thread::sleep_for(std::chrono::seconds(1));
		} break;
		}
	});
	LOG4I("myccd stoping...");
	//停止
	ZQCalcStop(ZQDB_STOP_FLAG_NONE);
	//结束
	ZQCalcTerm();
	return 0;
}


